//
// Created by Gao Shihao on 2023/8/11.
//

#include <plc2llvm/TypeSystem/TypeMachine.h>
#include <iostream>
#include <plc2llvm/TypeSystem/Basic/BasicInclude.h>
#include <plc2llvm/TypeSystem/UserDef/UDInclude.h>
#include <plc2llvm/TypeSystem/POU/POUInclude.h>
#include <memory>
#include <cassert>

using namespace plcst;

#define makeBasicType(tk) new tk##Type(#tk)

// 如果有循环枚举该多好
std::vector<std::shared_ptr<Type>> TypeMachine::creatAllBasicType() {
    std::vector<std::shared_ptr<Type>> res;
    res.emplace_back(makeBasicType(SINT));
    res.emplace_back(makeBasicType(INT));
    res.emplace_back(makeBasicType(DINT));
    res.emplace_back(makeBasicType(LINT));
    res.emplace_back(makeBasicType(USINT));
    res.emplace_back(makeBasicType(UINT));
    res.emplace_back(makeBasicType(UDINT));
    res.emplace_back(makeBasicType(ULINT));
    res.emplace_back(makeBasicType(REAL));
    res.emplace_back(makeBasicType(LREAL));
    res.emplace_back(makeBasicType(TIME));
    res.emplace_back(makeBasicType(LTIME));
    res.emplace_back(makeBasicType(DATE));
    res.emplace_back(makeBasicType(LDATE));
    res.emplace_back(makeBasicType(TOD));
    res.emplace_back(makeBasicType(LTOD));
    res.emplace_back(makeBasicType(DT));
    res.emplace_back(makeBasicType(LDT));
    res.emplace_back(makeBasicType(STRING));
    res.emplace_back(makeBasicType(WSTRING));
    res.emplace_back(makeBasicType(CHAR));
    res.emplace_back(makeBasicType(WCHAR));
    res.emplace_back(makeBasicType(BOOL));
    res.emplace_back(makeBasicType(BYTE));
    res.emplace_back(makeBasicType(WORD));
    res.emplace_back(makeBasicType(DWORD));
    res.emplace_back(makeBasicType(LWORD));

    return res;
}

bool TypeMachine::isNumber(TypeKind t) {
    return bool(this->isReal(t) || this->isInt(t));
}

bool TypeMachine::isReal(TypeKind t){
    return bool(this->realTypeKinds.count(t));
}

bool TypeMachine::isInt(TypeKind t){
    return bool(this->intTypeKinds.count(t));
}

bool TypeMachine::isSignedInt(TypeKind t) {
    return bool(this->signedIntTypeKind.count(t));
}

bool TypeMachine::isUnsignedInt(TypeKind t) {
    return bool(this->unsignedIntTypeKind.count(t));
}

bool TypeMachine::isBitstr(TypeKind t) {
    return bool(this->bitstrTypeKinds.count(t));
}

bool TypeMachine::isDateTime(TypeKind t) {
    return (t == TypeKind::DT || t == TypeKind::LDT);
}

bool TypeMachine::isDateType(TypeKind t) {
    return (t == TypeKind::DATE || t == TypeKind::LDATE);
}

bool TypeMachine::isDayType(TypeKind t) {
    return (t == TypeKind::TOD || t == TypeKind::LTOD);
}

bool TypeMachine::isDuringType(TypeKind t) {
    return (t == TypeKind::TIME || t == TypeKind::LTIME);
}

bool TypeMachine::isString(TypeKind t) {
    return (t == TypeKind::STRING || t == TypeKind::WSTRING || 
            t == TypeKind::CHAR || t == TypeKind::WCHAR);
}

bool TypeMachine::isWString(TypeKind t) {
    return (t == TypeKind::WSTRING || t == TypeKind::WCHAR);
}





